package com.br.aiops.listeners.ladder;

import com.br.aiops.counter.AlertLogCounter;
import com.br.aiops.counter.CounterLadderValue;
import com.br.aiops.cycle.Cycle;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 阶梯统计状态
 */
@Data
public class LadderCycleStatus {
    private static final Logger LOGGER = LoggerFactory.getLogger(LadderCycleStatus.class);
    /**
     * 每个区间的状态，key为区间起始结束时间字符串
     */
    private Map<String, Status> ladderCounter = new ConcurrentHashMap<>();

    private AlertLogCounter counter;

    private LadderCycleList ladderCycleList;

    /**
     * fastjson反序列化用该构造函数
     */
    public LadderCycleStatus() {}

    public LadderCycleStatus(AlertLogCounter counter) {
        this.counter = counter;
    }

    public void initCycle() {
        LOGGER.info("初始化阶梯。");
        ladderCycleList = new LadderCycleList(counter.getAlertLog().getLogTime(), counter.getRule().getDuration(),
                CounterLadderValue.getLadderValue(counter.counterKey()).getDurStep());
        //初始化status
        ladderCycleList.getCycles().forEach(cycle -> ladderCounter.putIfAbsent(cycle.cycleKey(),
                Status.builder().cycleStart(cycle.getStart()).cycleEnd(cycle.getEnd()).build()));
    }

    public boolean hasFlag(Date date) {
        Cycle cycle = ladderCycleList.getCycle(date);
        return !ladderCounter.containsKey(cycle.cycleKey()) || !ladderCounter.get(cycle.cycleKey()).isFlag();
    }

    public void flag(Date date) {
        Cycle cycle = ladderCycleList.getCycle(date);
        ladderCounter.get(cycle.cycleKey()).setFlag(true);
    }

    public void count(Date date) {
        Cycle cycle = ladderCycleList.getCycle(date);
        ladderCounter.compute(cycle.cycleKey(), (k, v) -> {
            if (v == null) {
                v = Status.builder().cycleStart(cycle.getStart()).cycleEnd(cycle.getEnd()).build();
                v.setCount(1L);
            } else {
                v.setCount(v.getCount() + 1);
            }
            return v;
        });
    }

    public long getCount(Date date) {
        Cycle cycle = ladderCycleList.getCycle(date);
        LadderCycleStatus.Status status = ladderCounter.get(cycle.cycleKey());
        if (Objects.nonNull(status)) {
            return status.getCount();
        }
        return 0L;
    }

    public int getCurrentDuration(Date date) {
        Cycle cycle = ladderCycleList.getCycle(date);
        return cycle.getDuration();
    }

    public boolean beforeFirstCycle(Date date) {
        long minute = Long.parseLong(FastDateFormat.getInstance("yyyyMMddHHmm").format(date));
        return minute < ladderCycleList.getCycles().get(0).getStart();
    }

    public Map<String, Status> getLadderCounter() {
        return ladderCounter;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Status {
        private long count;
        private boolean flag;
        private long cycleStart;
        private long cycleEnd;
    }
}
